﻿using Newtonsoft.Json;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Zocono.Infrastructure.Common;
using Zocono.WCS.Domain.DomainRepository;
using Zocono.WCS.Domain.EntityInfo;
using Zocono.WCS.Domain.LogDomain;
using Zocono.WCS.Domain.PlcBytesObject;
using Zocono.WCS.Domain.PlcConnectPoolDomain;
using Zocono.WCS.Domain.ProcessModuleDomain;
using Zocono.WCS.Infrastructure.ApllicationDto.Enums;
using Zocono.WCS.Infrastructure.ApllicationDto.WCSTaskDto;
using Zocono.WCS.Infrastructure.PlcCommon;
using Zocono.WCS.WMSApiDomain.WebApi;

namespace Zocono.WCS.Domain.EquipmentProcessDomain.PlanarMessage
{
    public class PlanarPutBatteryPlcActionBOMessageService : IPlanarActionMessageService
    {
        private readonly ISnowflake _snowflake;
        private readonly IPlcConnectionPool _PlcConnectionPool;
        private readonly IPlcWriteDbInfoRepository _PlcWriteDbInfoRepository;
        private readonly ITelegramRecordInfoRepository _TelegramRecordInfoRepository;
        private readonly IWorkTaskInfoRepository _workTaskInfoRepository;
        private readonly IPlcConnectionStateInfoRepository _IPlcConnectionStateInfoRepository;
        private readonly IRunLogInfoService _IRunLogInfoService;
        private readonly IPlcReadDbInfoRepository _PlcReadeDbInfoRepository;
        public PlanarPutBatteryPlcActionBOMessageService(ISnowflake snowflake, IPlcConnectionPool plcConnectionPool
            , IPlcWriteDbInfoRepository plcWriteDbInfoRepository
            , ITelegramRecordInfoRepository telegramRecordInfoRepository
            , IWorkTaskInfoRepository workTaskInfoRepository
                , IPlcConnectionStateInfoRepository plcConnectionStateInfoRepository
            , IRunLogInfoService iRunLogInfoService, IPlcReadDbInfoRepository plcReadDbInfoRepository)
        {
            _snowflake = snowflake;
            _PlcConnectionPool = plcConnectionPool;
            _PlcWriteDbInfoRepository = plcWriteDbInfoRepository;
            _TelegramRecordInfoRepository = telegramRecordInfoRepository;
            _workTaskInfoRepository = workTaskInfoRepository;
            _IPlcConnectionStateInfoRepository = plcConnectionStateInfoRepository;
            _IRunLogInfoService = iRunLogInfoService;
            _PlcReadeDbInfoRepository = plcReadDbInfoRepository;
        }
        public async Task ProcessActionMessageAsync(BytesObjectBase actionMessage, EquipmentDbObject planarEquipmentDbObject)
        {
            /*
             * 判断是否有请求，有请求则获取位置信息和条码，将数据传到WMS等待校验结果
             */
            var plcMessage = actionMessage as PlanarPutBatteryPlcActionBO;

            plcMessage.PalletBarcode = plcMessage.PalletBarcode.Trim();
            plcMessage.BatteryCode=plcMessage.BatteryCode.Trim();
            var objectType = typeof(PlanarPutBatteryWriteWcsActionBO).Name;
            var writeConfig = await _PlcWriteDbInfoRepository.GetFirstAsync(l => l.EquipmentCode == plcMessage.EquipmentCode && l.ObjectType == objectType);

            RunLogInfo runLogInfo = new RunLogInfo();
            runLogInfo.ContainerBarcode = plcMessage.PalletBarcode;
            runLogInfo.EquipmentCode = plcMessage.EquipmentCode;
            runLogInfo.RunType = "投料口校验";

            PlcConnectionS7 plcConnect = _PlcConnectionPool.S7GetWritePlcConnection(plcMessage.PlcConnectionID); ;//plc写入连接（不锁定）
            var plcstate = await _IPlcConnectionStateInfoRepository.GetFirstAsync(l => l.PlcConnectionID == plcMessage.PlcConnectionID && l.Connected == true);
            if (plcstate == null)
            {
                runLogInfo.RunLog = $"{plcConnect.IP}plc已离线";
                await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                return;
            }


            PlanarPutBatteryWriteWcsActionBO writebo = new();
            writebo.EquipmentCode = plcMessage.EquipmentCode.ToInt32();
            writebo.ToEquipmentCode = plcMessage.ToEquipmentCode;
            writebo.TaskCode = plcMessage.TaskCode;
            writebo.ActionType = plcMessage.ActionType;

            if (plcMessage.ActionType == 35 || plcMessage.ActionType == 37)
            {
                //实盘校验
                if (plcMessage.ActionType == 35)
                {
                    WCSCombinePalletInfoDto wCSCombinePalletInfoDto = new()
                    {
                        ContainerBarcode = plcMessage.PalletBarcode,
                        EquipmentCode = plcMessage.EquipmentCode
                    };

                    List<WCSOneBatteryDto> list = new()
                    {
                        new WCSOneBatteryDto()
                        {
                            BatteryIndex = plcMessage.BatteryIndex,
                            BatteryCode = plcMessage.BatteryCode
                        }
                    };

                    wCSCombinePalletInfoDto.oneBatteryInfoDtos = list;
                    //组盘提交数据到WMS
                    var bo = await WCSMessageWithWMSApi.WCSAddComPalletAsync(wCSCombinePalletInfoDto);
                    if (bo)
                    {
                        runLogInfo.RunLog = $"投料校验成功";
                        await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                    }
                    else
                    {
                        writebo.ActionType = 6;
                        var res = await plcConnect.WriteDbAsync(writeConfig.DbCode, writeConfig.DbStart, writebo.Deserialize());
                        if (res)
                        {
                            runLogInfo.RunLog = $"PLC(IP{plcConnect.IP})写入报文成功";
                            await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                        }
                        else
                        {
                            runLogInfo.RunLog = $"PLC(IP{plcConnect.IP})写入报文失败";
                            await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                        }
                        return;
                    }
                }

                #region wcs托盘上架任务已存在逻辑处理

                //判断设备在wcs是否已存在分配巷道任务
                var exp = Expressionable.Create<WorkTaskInfo>();
                exp.AndIF(true, (a) => a.PalletCode == plcMessage.PalletBarcode && (a.TaskState == EnumTaskState.Initial || a.TaskState == EnumTaskState.Executing));
                var wcsWorkTaskInfo = await _workTaskInfoRepository.GetFirstAsync(exp.ToExpression());
                //根据托盘是否存在其它的任务 && 起点位置是否相同判断，存在则写入正常报文Return
                if (wcsWorkTaskInfo != null /*&& wcsWorkTaskInfo.CurrentFromEquipment == plcMessage.EquipmentCode*/)
                {

                    runLogInfo.RunLog = $"请求分配重复:任务号：{wcsWorkTaskInfo.TaskCode}入库任务已存在";
                    await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);

                    //针对wcs任务为初始化的处理成执行中并同步更新wms任务状态
                    if (wcsWorkTaskInfo.TaskState == EnumTaskState.Initial || wcsWorkTaskInfo.TaskState == EnumTaskState.Executing)
                    {
                        wcsWorkTaskInfo.TaskState = EnumTaskState.Executing;
                        wcsWorkTaskInfo.UpdateTime = DateTime.Now;
                        wcsWorkTaskInfo.CurrentDetailTaskState = EnumDetailTaskState.Executing;
                        try
                        {
                            //同步更新wms任务状态
                            var flag = await WCSMessageWithWMSApi.WCSUpdateWMStaskStateAndProcessTaskStateAsync(wcsWorkTaskInfo.WmsTaskCode, (int)EnumTaskState.Executing);
                            if (flag)
                            {
                                wcsWorkTaskInfo.UploadWmsState = EnumUploadWmsState.Succeed;
                                wcsWorkTaskInfo.UploadWmsTime = DateTime.Now;
                            }
                        }
                        catch (Exception ex)
                        {

                            runLogInfo.RunLog = $"wms任务号{wcsWorkTaskInfo.TaskCode}同步状态更新失败";
                            await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                        }
                        //更新wcs任务状态为执行中
                        await _workTaskInfoRepository.UpdateAsync(wcsWorkTaskInfo);
                    }

                    //写入正常报文
                    writebo.TaskCode = wcsWorkTaskInfo.TaskCode;
                    writebo.ToEquipmentCode = wcsWorkTaskInfo.CurrentToEquipment.ToInt32();
                    var writeBl = await plcConnect.WriteDbAsync(writebo.DbCode, writebo.DbStart, writebo.Deserialize());
                    if (!writeBl)
                    {
                        runLogInfo.RunLog = $"请求分配重复:写入正常报文报文失败";
                        await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);

                        return;
                    }
                    else
                    {
                        runLogInfo.RunLog = $"请求分配重复:写入正常报文报文成功";
                        await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);

                    }
                    return;
                }
                #endregion


                WmsTaskInfoDto workTaskDto = null;
                try
                {
                    //向wms读取巷道分配任务
                    WMSApiDomain.WebApi.HeaderResult<WmsTaskInfoDto> res = await WCSMessageWithWMSApi.WCSCreatUploadWarehouseWMSTaskAsync(plcMessage.PalletBarcode, plcMessage.EquipmentCode);
                    if (res.IsSucceed)
                    {
                        workTaskDto = res.Result;
                    }
                    else
                    {
                        var msg = res.Message;
                        runLogInfo.RunLog = $"向Wms请求任务失败:{msg}";
                        await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                        return;
                    }

                }
                catch (Exception ex)
                {
                    if (ex.Message.Contains("at") && ex.Message.Contains("System.Exception:"))
                    {
                        var msg = ex.Message.Split("at").First().Split("System.Exception:");
                        runLogInfo.RunLog = $"向Wms请求任务失败:{msg[1]}";

                    }
                    else
                    {
                        var msg = ex.Message.Length > 150 ? ex.Message.Substring(0, 100) : ex.Message;
                        runLogInfo.RunLog = $"向Wms请求任务失败:{msg}";
                    }
                    await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                }
                if (workTaskDto == null)
                {
                    runLogInfo.RunLog = $"向Wms请求任务失败WMS返回空";
                    await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                    return;
                }


                //WorkTaskInfo数据补全
                var workTaskInfo = new WorkTaskInfo();

                long id = _snowflake.GetId();//雪花ID
                workTaskInfo.ID = id;
                //wcs任务code从wmstaskcode日开始截取
                int.TryParse(workTaskDto.TaskCode.ToString().Substring(6), out var wcsTaskCode);
                workTaskInfo.TaskCode = wcsTaskCode;
                //wms赋值
                workTaskInfo.WmsTaskCode = workTaskDto.TaskCode;
                workTaskInfo.DependWmsTaskCode = workTaskDto.DependWMSTaskCode;
                workTaskInfo.TaskType = Enum.Parse<EnumTaskType>(workTaskDto.TaskType.ToString());

                workTaskInfo.WmsFromPosition = workTaskDto.StartPosition;
                workTaskInfo.WmsToPosition = workTaskDto.EndPosition;
                workTaskInfo.WmsFromStation = workTaskDto.FromStation;
                workTaskInfo.WmsToStation = workTaskDto.ToStation;
                workTaskInfo.TaskProcessState = EnumTaskProcessState.Initial;
                workTaskInfo.TaskState = EnumTaskState.Executing;
                workTaskInfo.Priority = workTaskDto.Priority;

                //托盘条码
                workTaskInfo.PalletCode = plcMessage.PalletBarcode.Trim();


                #region 任务子任务信息赋值by RouteDetailInfo
                //获取配置巷道信息
                var routeConfigExp = Expressionable.Create<RouteInfo>();
                routeConfigExp.AndIF(true, (a) => a.FromStation == workTaskInfo.WmsFromStation && a.ToStation == workTaskInfo.WmsToStation);
                var routeInfo = await _workTaskInfoRepository.AsSugarClient()
                    .Queryable<RouteInfo>()
                    .Where(routeConfigExp.ToExpression())
                    .Select((a) => new RouteInfo()
                    {
                        ID = a.ID,
                        FromStation = a.FromStation,
                        ToStation = a.ToStation,
                    }).FirstAsync();
                if (routeInfo == null)
                {
                    runLogInfo.RunLog = $"起始工位{workTaskInfo.WmsFromStation}目标工位{workTaskInfo.WmsToStation}获取工位失败";
                    await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                    return;
                }

                //巷道详情信息获取
                var routeDetailConfigExp = Expressionable.Create<RouteDetailInfo>();
                routeDetailConfigExp.AndIF(true, (a) => a.RouteID == routeInfo.ID && a.IsStart);
                var routeDetailInfo = await _workTaskInfoRepository.AsSugarClient()
                    .Queryable<RouteDetailInfo>()
                    .Where(routeDetailConfigExp.ToExpression())
                    .Select((a) => new
                    {
                        a.ID,
                        a.RouteID,
                        a.FromCargo,
                        a.ToCargo,
                        a.DispatchType,
                        a.FromEquipment,
                        a.ToEquipment,

                    }).FirstAsync();

                if (routeDetailInfo == null)
                {
                    runLogInfo.RunLog = $"巷道路径详情配置信息起始工位{workTaskInfo.WmsFromStation}目标工位{workTaskInfo.WmsToStation}获取设备路径失败";
                    await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                    return;
                }

                workTaskInfo.CurrentToEquipment = routeDetailInfo.ToEquipment;


                workTaskInfo.CurrentFromCargo = routeDetailInfo.FromCargo;
                workTaskInfo.CurrentToCargo = routeDetailInfo.ToCargo;
                workTaskInfo.RouteID = routeDetailInfo.RouteID;
                workTaskInfo.CurrentRounteDetailID = routeDetailInfo.ID;
                workTaskInfo.CurrentDispatchType = routeDetailInfo.DispatchType;
                //起始设备位 
                workTaskInfo.CurrentFromEquipment = workTaskInfo.WmsFromPosition; //WMS 作业实际起点设备
                                                                                  // workTaskInfo.CurrentToEquipment = routeDetailInfo.ToEquipment;
                workTaskInfo.CurrentDetailTaskState = EnumDetailTaskState.Executing;
                workTaskInfo.CurrentCreateTime = DateTime.Now;
                workTaskInfo.CurrentUpdateTime = DateTime.Now;
                #endregion

                workTaskInfo.SaveTime = DateTime.Now;
                workTaskInfo.UpdateTime = DateTime.Now;

                #region 同步更新wms任务状态&写入正常报文
                //写入正常报文到Plc
                writebo.TaskCode = workTaskInfo.TaskCode;//wcs任务号
                writebo.ToEquipmentCode = workTaskInfo.CurrentToEquipment.ToInt32();//目标设备编号

                runLogInfo.RunLog = $"PLC写入报文内容： {JsonConvert.SerializeObject(writebo)}";
                await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                var writeResult = await plcConnect.WriteDbAsync(writebo.DbCode, writebo.DbStart, writebo.Deserialize());

                if (writeResult == false)
                {
                    runLogInfo.RunLog = $"PLC(IP{plcConnect.IP})写入报文失败";
                    await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                    return;
                }
                else
                {
                    runLogInfo.RunLog = $"PLC(IP{plcConnect.IP})写入报文成功";
                    await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                }


                try
                {
                    //同步更新wms任务状态为执行中
                    var flag = await WCSMessageWithWMSApi.WCSUpdateWMStaskStateAndProcessTaskStateAsync(workTaskInfo.WmsTaskCode, (int)EnumTaskState.Executing);
                    if (flag)
                    {
                        workTaskInfo.UploadWmsState = EnumUploadWmsState.Succeed;
                        workTaskInfo.UploadWmsTime = DateTime.Now;
                    }
                }
                catch (Exception ex)
                {
                    if (ex.Message.Contains("at") && ex.Message.Contains("System.Exception:"))
                    {

                        var msg = ex.Message.Split("at").First().Split("System.Exception:");
                        runLogInfo.RunLog = $"任务号{workTaskInfo.WmsTaskCode}:向Wms同步状态更新失败:{msg[1]}";

                    }
                    else
                    {
                        var msg = ex.Message.Length > 150 ? ex.Message[..100] : ex.Message;
                        runLogInfo.RunLog = $"任务号{workTaskInfo.WmsTaskCode}:向Wms同步状态更新失败:{msg}";
                    }
                    await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                }

                //WorkTaskInfo数据插入
                var expCheck = Expressionable.Create<WorkTaskInfo>();
                expCheck.AndIF(true, (a) => a.PalletCode == plcMessage.PalletBarcode && (a.TaskState == EnumTaskState.Initial || a.TaskState == EnumTaskState.Executing));
                var wcsCheckWorkTaskInfo = await _workTaskInfoRepository.GetFirstAsync(expCheck.ToExpression());
                if (wcsCheckWorkTaskInfo == null)
                {
                    bool bl = await _workTaskInfoRepository.InsertAsync(workTaskInfo);
                }

                #endregion


            }

            var plcConfigput = await _PlcReadeDbInfoRepository.GetFirstAsync(l => l.EquipmentCode == plcMessage.EquipmentCode);


            byte[] bytes = await plcConnect.ReadDbAsync(plcConfigput.DbCode, plcConfigput.DbStart, plcConfigput.DbLength);
            if (bytes == null)
            {
                runLogInfo.RunLog = $"读DB失败";
                await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                return;
            }

            PlanarPutBatteryWcsActionBO plcActionBO = new();
            plcActionBO.Serialize(plcConfigput.PlcConnectionID, plcConfigput.ID, plcConfigput.DbStart, plcConfigput.DbLength, plcConfigput.DbStart, plcConfigput.DbLength, "ElevatorGeneralPlcActionBO", plcConfigput.EquipmentCode, bytes);//主要是bytes转化成明文
            //清数据
            if(plcMessage.ActionType==0&& plcActionBO.ActionType > 0)
            {
                writebo.ToEquipmentCode = 0;
                writebo.TaskCode = 0;
                writebo.ActionType = 0; 
                var writeResult = await plcConnect.WriteDbAsync(writebo.DbCode, writebo.DbStart, writebo.Deserialize());

                if (writeResult == false)
                {
                    runLogInfo.RunLog = $"PLC(IP{plcConnect.IP})写入报文失败";
                    await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                    return;
                }
                else
                {
                    runLogInfo.RunLog = $"PLC(IP{plcConnect.IP})写入报文成功";
                    await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                }
            }


        }
    }
}
